#include "GError.h"
#include "GInitializable.h"


namespace GUtil
{
	// Description: Constructor
	// Return:
	// Notes:
	// ----------------------------------------------------
	GInitializable::GInitializable()
	{
		InitState.store(G_IS_UNINITIALIZED, std::memory_order_release);
	}

	// Description: Destructor
	// Return:
	// Notes: Triggers an error if instance did not Uninitialize correctly
	// ----------------------------------------------------
	GInitializable::~GInitializable()
	{
		GError::DebugCheck(GetInitializationState() != G_IS_UNINITIALIZED, "GInitializable beind deleted is not uninitialized!");
	}

	// Description: Returns the state of the initializable
	// Return:
	// Notes:
	// ----------------------------------------------------
	GInitState GInitializable::GetInitializationState() const
	{
		return InitState.load(std::memory_order_acquire);
	}

	// Description: Expects state to be G_IS_UNINITIALIZED and changes the state to G_IS_INITIALIZING
	// Return:
	// Notes: Inheriting classes should call and check the return of this function. If return is false it means that instance already initialized!
	// ----------------------------------------------------
	bool GInitializable::Initialize()
	{
		if (GetInitializationState() == G_IS_UNINITIALIZED)
		{
			InitState.store(G_IS_INITIALIZING, std::memory_order_release);
			return true;
		}
		return false;
	}

	// Description: Expects state to be G_IS_INITIALIZING and changes the state to G_IS_INITIALIZED
	// Return:
	// Notes1: Inheriting classes should call and check the return of this function. If return is false it means that instance already initialized!
	// Notes2: Called automatically after Initialize() and intended to contain registry routines to other systems
	// ----------------------------------------------------
	bool GInitializable::InitializeLate()
	{
		if (GetInitializationState() == G_IS_INITIALIZING)
		{
			InitState.store(G_IS_INITIALIZED, std::memory_order_release);
			return true;
		}
		return false;
	}

	// Description: Changes the state to G_IS_UNINITIALIZED
	// Return:
	// Notes:
	// ----------------------------------------------------
	void GInitializable::Uninitialize()
	{
		InitState.store(G_IS_UNINITIALIZED, std::memory_order_release);
	}

	// Description: Changes the state to G_IS_UNINITIALIZING
	// Return:
	// Notes: Called before Uninitialize() automatically and is inteded to use cut the communication with other systems before actual deinitializetion
	// ----------------------------------------------------
	void GInitializable::UninitializeEarly()
	{
		InitState.store(G_IS_UNINITIALIZING, std::memory_order_release);
	}

}; // namespace GUtil